package com.collabscm.pf.util;

import java.lang.reflect.Method;
import java.util.List;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;
import net.sf.json.util.JSONUtils;

import org.apache.commons.collections.KeyValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.collabscm.pf.BaseObject;
import com.collabscm.pf.IBaseObject;
import com.collabscm.pf.cache.Cache;
import com.collabscm.pf.cache.CacheManager;
import com.collabscm.pf.cache.CacheManagerFactory;
import com.collabscm.pf.model.DomainObject;

/**
 * JSON处理的工具类
 * 
 * @author Zeng Raoxing
 */
public class JsonUtils {
	/**
	 * JSON转化的配置
	 */
	private static JsonConfig jsonConfig = new ExtJsonConfig();
	/**
	 * Class的json的对应关系。
	 */
	private static Cache<Class<?>, ObjectSerializable<Method>> typeToJSON;
	private static Logger logger = LoggerFactory.getLogger(JsonUtils.class);
	
	static {
		@SuppressWarnings("unchecked")
		CacheManager<Cache<Class<?>, ObjectSerializable<Method>>> cm = CacheManagerFactory.getCacheManager();
		typeToJSON = cm.getCache("platform/utils/JsonUtils");
	}
	
	/**
	 * 生成JSON对象的字符串
	 * @param values
	 */
	public static String makeJsonObjectString(List<KeyValue> values) {
		StringBuffer sb = new StringBuffer("{");
		if(!values.isEmpty()) {
			for(KeyValue value: values) {
				sb.append(JSONUtils.quote( value.getKey().toString()));
	            sb.append(':');
	            sb.append(JSONUtils.quote( value.getValue().toString()));
	            sb.append(',');
			}
			sb.deleteCharAt(sb.length() - 1);//删除最后一个逗号
		}
		sb.append("}");
		return sb.toString();
	}

	/**
	 * 生成Json对象的串，注意：对象串是以{}包围的。
	 * @param object 待转换的对象
	 */
	public static String toJsonObjectString(Object object) {
		Method m = getToJSONStringMethod(object.getClass());
		if(m == null) {
			return defaultToJsonObjectString(object);
		} else {
			return (String) ReflectionUtils.invokeMethod(m, object);
		}
	}
	
	/**
	 * 默认的ToJsonObjectString的实现，主要为了防止出现无限循环
	 * 
	 * @param object
	 */
	public static String defaultToJsonObjectString(Object object) {
		return JSONObject.fromObject(object, jsonConfig).toString();
	}

	/**
	 * 生成Json数组的串，注意：数组串是以[]包围的。
	 * @param arrayObject Collection或数组
	 */
	public static String toJsonArrayString(Object arrayObject){
		return JSONArray.fromObject(arrayObject, jsonConfig).toString();
	}
	
	/**
	 * 得到toJSONString方法
	 * @param clazz 类
	 * @return
	 */
	private static Method getToJSONStringMethod(Class<?> clazz) {
		if(typeToJSON.containsKey(clazz)) {
			return typeToJSON.get(clazz).getObject();
		} else {
			Method method = null;
			if(IBaseObject.class.isAssignableFrom(clazz)) {//判断是否是IBaseObject的子类
				method = ReflectionUtils.getMethod(clazz, IBaseObject.toJSONStringMethodName);
				if(method != null) {
					clazz = method.getClass();
					if(validateBaseObjectClass(clazz)) {
						method = null;
					}
				}
				typeToJSON.put(clazz, new ObjectSerializable<Method>(method));
			}
			return method;
		}
	}

	/**
	 * 验证类是否是系统提供的基类
	 */
	private static boolean validateBaseObjectClass(Class<?> clazz) {
		return clazz == BaseObject.class || clazz == DomainObject.class;
	}
	
	/**
	 * Json-lib配置的扩展类，目标是对toJSONString的处理。
	 */
	public static class ExtJsonConfig extends JsonConfig {
		/**
		 * 添加对日期的处理
		 */
		public ExtJsonConfig() {
			
		}
		
		private JsonValueProcessor jsonValueProcessor = new JsonValueProcessor() {
			@Override
			public Object processArrayValue(Object value, JsonConfig jsonConfig) {
				if(value instanceof IBaseObject) {
					return ((IBaseObject) value).toJSONString();
				}
				return "ERROR: this is not instanceof IBaseObject.";
			}

			@Override
			public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) {
				if(value instanceof IBaseObject) {
					return ((IBaseObject) value).toJSONString();
				}
				return "ERROR: " + key + " is not instanceof IBaseObject.";
			}
		};
		
		@SuppressWarnings("unchecked")
		@Override
		public JsonValueProcessor findJsonValueProcessor(Class beanClass, Class propertyType, String key) {
			if(validateClass(propertyType)) {
				if(logger.isDebugEnabled()) {
					logger.debug("Call findJsonValueProcessor: " + propertyType+ ". the beanCalss:" + beanClass + ", the key:" + key);
				}
				return jsonValueProcessor;
			}
			return super.findJsonValueProcessor(beanClass, propertyType, key);
		}

		@SuppressWarnings("unchecked")
		@Override
		public JsonValueProcessor findJsonValueProcessor(Class propertyType) {
			if(validateClass(propertyType)) {
				if(logger.isDebugEnabled()) {
					logger.debug("Call findJsonValueProcessor: " + propertyType);
				}
				return jsonValueProcessor;
			}
			return super.findJsonValueProcessor(propertyType);
		}
		
		@SuppressWarnings("unchecked")
		@Override
		public JsonValueProcessor findJsonValueProcessor(Class propertyType, String key) {
			if(validateClass(propertyType)) {
				if(logger.isDebugEnabled()) {
					logger.debug("Call findJsonValueProcessor: " + propertyType + ". the key:" + key);
				}
				return jsonValueProcessor;
			}
			return super.findJsonValueProcessor(propertyType, key);
		}
		
		/**
		 * 验证Class是否是可以特殊处理的Class。
		 * @param clazz
		 * @return
		 */
		private boolean validateClass(Class<?> clazz) {
			return getToJSONStringMethod(clazz) != null;
		}
		
	}

	/**
	 * Json配置对象
	 * @author Zeng Raoxing
	 */
	public class Configuration {
		/**
		 * 得到JsonConfig实例，这样可以供子类进行设置
		 */
		protected JsonConfig getJsonConfig() {
			return JsonUtils.jsonConfig;
		}
	}
}
